package level.editor.model.main;

import java.awt.Component;
import java.util.TreeMap;

import javax.swing.event.ChangeListener;

import level.editor.control.collision.CollisionLayer;
import level.editor.control.layer.Layer;
import level.editor.control.layer.LayerControl;
import level.editor.control.main.Main;
import level.editor.control.main.MainTabbed;
import level.editor.control.object.ObjectLayer;
import level.editor.control.tile.TileLayer;
import level.model.State;
import level.model.StateCollisionLayer;
import level.model.StateLayer;
import level.model.StateObjectLayer;
import level.model.StateTileLayer;
import level.model.utility.StateHandler;
import level.model.utility.StateSaver;

public class MainModel
{
	public MainModel(State state, Main main)
	{
		this.state = state;
		this.main = main;

		initiateMemento();
	}

	public void initiateState()
	{
		TreeMap<Integer, StateLayer> layers = state.getLayers();
		for (int i = 0; i <= main.MAX_STATE_LAYERS; i++)
		{
			if (main.getComponentCountInLayer(i) != 0)
			{
				for (Component layer : main
						.getComponentsInLayer(new Integer(i)))
				{
					if (layers.keySet().contains(i) && layer instanceof Layer)
					{
						Layer l = (Layer) layer;
						if (layers.get(i) instanceof StateTileLayer)
						{
							TileLayer tile = new TileLayer(
									(StateTileLayer) layers.get(i));
							tile.setLock(l.isLocked());
							tile.setVisible(l.isVisible());
							tile.setSelected(((TileLayer) l).isSelected());
							main.remove(l);
							main.addLayer(tile, tile.getLayerNumber());
							((TileLayer) tile).requestMinimap();
						}

						if (layers.get(i) instanceof StateCollisionLayer)
						{
							CollisionLayer coll = new CollisionLayer(
									(StateCollisionLayer) layers.get(i));
							coll.setLock(l.isLocked());
							coll.setVisible(l.isVisible());
							main.remove(l);
							main.addLayer(coll, coll.getLayerNumber());
						}
						
						if (layers.get(i) instanceof StateObjectLayer)
						{
							ObjectLayer obj = new ObjectLayer(
									(StateObjectLayer) layers.get(i));
							obj.setLock(l.isLocked());
							obj.setVisible(l.isVisible());
							main.remove(l);
							main.addLayer(obj, obj.getLayerNumber());
						}
					}
					else
						main.remove(layer);
				}
			}

			else
			{
				if (layers.keySet().contains(i)
						&& layers.get(i) instanceof StateTileLayer)
				{
					TileLayer layer = new TileLayer(
							(StateTileLayer) layers.get(i));
					if (main.getComponentsInLayer(layer.getLayerNumber()).length == 0)
						main.addLayer(layer, layer.getLayerNumber());
					((TileLayer) layer).requestMinimap();
				}

				if (layers.get(i) instanceof StateCollisionLayer)
				{
					CollisionLayer layer = new CollisionLayer(
							(StateCollisionLayer) layers.get(i));
					if (main.getComponentsInLayer(layer.getLayerNumber()).length == 0)
						main.addLayer(layer, layer.getLayerNumber());
				}
				
				if (layers.get(i) instanceof StateObjectLayer)
				{
					ObjectLayer layer = new ObjectLayer(
							(StateObjectLayer) layers.get(i));
					if (main.getComponentsInLayer(layer.getLayerNumber()).length == 0)
						main.addLayer(layer, layer.getLayerNumber());
				}
			}
		}
		main.repaint();
	}

	public String getName()
	{
		String dirty = StateHandler.UNMODIFIED_PREFIX;
		if (main.getClientProperty(Main.DIRTY_PROPERTY) != null)
		{
			if (main.getClientProperty(Main.DIRTY_PROPERTY) == Main.DIRTY)
				dirty = StateHandler.MODIFIED_PREFIX;
		}
		return dirty + state.getFile().getName();
	}

	public State getState()
	{
		return state;
	}

	public void setState(State state)
	{
		this.state = state;
	}

	public void save()
	{
		StateSaver.save(state);
		updateFile();
	}

	public boolean saveAs()
	{
		return StateSaver.saveAs(state);
	}

	public boolean undo()
	{
		if (memento.undo(this))
		{
			initiateState();
			updateLayerControl();
			main.paintFromState();
			return true;
		}
		else
			return false;
	}

	public boolean redo()
	{
		if (memento.redo(this))
		{
			initiateState();
			updateLayerControl();
			main.paintFromState();
			return true;
		}
		else
			return false;
	}

	public void createMemento()
	{
		memento.add(StateHandler.copy(state));
	}

	public void updateFile()
	{
		memento.updateFile(state.getFile());
	}

	private void initiateMemento()
	{
		memento = new StateMemento(StateHandler.copy(state));
	}

	private void updateLayerControl()
	{
		MainTabbed tabbed = main.getMainTabbed();
		if (tabbed != null)
		{
			for (ChangeListener listener : tabbed.getChangeListeners())
			{
				if (listener instanceof LayerControl)
				{
					LayerControl control = (LayerControl) listener;
					control.updateChange(tabbed);
				}
			}
		}
	}

	private State state;
	private Main main;
	private StateMemento memento;
}
